package com.sita.tboard.ui.my;

import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.design.widget.Snackbar;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import android.widget.Toast;

import com.afollestad.materialdialogs.MaterialDialog;
import com.colintmiller.simplenosql.NoSQL;
import com.colintmiller.simplenosql.NoSQLEntity;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.sita.bike.R;
import com.sita.bike.persistence.Person;
import com.sita.bike.rest.model.Account;
import com.sita.bike.rest.model.response.AccountUpdateResponse;
import com.sita.bike.support.Constants;
import com.sita.bike.support.GlobalContext;
import com.sita.bike.utils.PersistUtils;
import com.sita.tboard.ActivityBase;
import com.sita.tboard.advertisement.AdvertiseManager;
import com.sita.tboard.global.AccountManager;
import com.sita.tboard.util.TextUtils;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.picasso.Callback;
import com.squareup.picasso.Picasso;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.concurrent.TimeUnit;

import butterknife.Bind;
import butterknife.ButterKnife;
import butterknife.OnClick;
import de.hdodenhof.circleimageview.CircleImageView;
import pl.aprilapps.easyphotopicker.DefaultCallback;
import pl.aprilapps.easyphotopicker.EasyImage;
import pl.tajchert.nammu.Nammu;
import pl.tajchert.nammu.PermissionCallback;
import retrofit.RequestInterceptor;
import retrofit.RestAdapter;
import retrofit.RetrofitError;
import retrofit.client.OkClient;
import retrofit.client.Response;
import retrofit.converter.GsonConverter;
import retrofit.http.Multipart;
import retrofit.http.POST;
import retrofit.http.Part;
import retrofit.mime.TypedFile;
import retrofit.mime.TypedString;

public class MyProfileActivity extends ActivityBase {

    @Bind(R.id.root_layout)
    LinearLayout mParentView;

    @Bind(R.id.toolbar)
    Toolbar toolbar;

    @Bind(R.id.avatar)
    CircleImageView avatarView;
    @Bind(R.id.nickname)
    EditText nicknameView;
    @Bind(R.id.birthday)
    EditText birthdayView;
    @Bind(R.id.gender)
    EditText genderView;
    @Bind(R.id.address)
    EditText addressView;
    @Bind(R.id.signature)
    EditText signatureView;

    private Account mAccount;

    private class ModelAccount {
        String userId = "";
        String avatar = "";
        String nickname = "";
        String signature = "";

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            ModelAccount that = (ModelAccount) o;

            if (userId != null ? !userId.equals(that.userId) : that.userId != null) return false;
            if (avatar != null ? !avatar.equals(that.avatar) : that.avatar != null) return false;
            if (nickname != null ? !nickname.equals(that.nickname) : that.nickname != null)
                return false;
            return !(signature != null ? !signature.equals(that.signature) : that.signature != null);

        }

        @Override
        public int hashCode() {
            int result = userId != null ? userId.hashCode() : 0;
            result = 31 * result + (avatar != null ? avatar.hashCode() : 0);
            result = 31 * result + (nickname != null ? nickname.hashCode() : 0);
            result = 31 * result + (signature != null ? signature.hashCode() : 0);
            return result;
        }
    }

    public interface UpdateService {

        @Multipart
        @POST("/usermgmt/v1/accounts/update")
        void update(@Part("avatar") TypedFile avatar,
                    @Part("params") TypedString params, retrofit.Callback<AccountUpdateResponse> callback);
    }

    private ModelAccount origAcct = new ModelAccount();
    private ModelAccount editAcct = new ModelAccount();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my_profile);
        ButterKnife.bind(this);

        setSupportActionBar(toolbar);
        ActionBar actionBar = getSupportActionBar();
        actionBar.setDisplayHomeAsUpEnabled(true);
        actionBar.setTitle(null);
        toolbar.setNavigationIcon(R.mipmap.ic_back);

        mAccount = AccountManager.getInstance().getAccount();
        if (mAccount == null) {
            finish();
            return;
        }

        origAcct.nickname = mAccount.mNickName;
        origAcct.signature = mAccount.mSignature;
        origAcct.userId = mAccount.mAccountId;

        Picasso.with(GlobalContext.getGlobalContext()).load(mAccount.mAvatar).fit().centerInside()
                .into(avatarView, new Callback() {
                    @Override
                    public void onSuccess() {
                        Bitmap bitmap = ((BitmapDrawable) avatarView.getDrawable()).getBitmap();
                        Uri uri = getImageUri(MyProfileActivity.this, bitmap);
                        avatarView.setTag(getRealPathFromURI(uri));
                        origAcct.avatar = (String) avatarView.getTag();
                    }

                    @Override
                    public void onError() {
                    }
                });

        nicknameView.setText(mAccount.mNickName);

        if (mAccount.mGender == 0) {
            genderView.setText(getString(R.string.unknown));
        }
        if (mAccount.mGender == 1) {
            genderView.setText(getString(R.string.male));
        }
        if (mAccount.mGender == 2) {
            genderView.setText(getString(R.string.famale));
        }
        birthdayView.setText(mAccount.mBirthday);
        addressView.setText(mAccount.mAddress);
        signatureView.setText(mAccount.mSignature);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_my_profile, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                finish();
                return true;
            case R.id.action_settings:
                return true;
            case R.id.action_complete: {
                clickCompleteButton();
                return true;
            }
        }
        return super.onOptionsItemSelected(item);
    }

    @OnClick(R.id.avatar)
    void clickAvatar() {
        openPopup();
    }

    void clickCompleteButton() {
        editAcct.nickname = TextUtils.nullIfEmpty(nicknameView.getText().toString());
        editAcct.avatar = TextUtils.nullIfEmpty((String) avatarView.getTag());
        editAcct.userId = TextUtils.nullIfEmpty(mAccount.mAccountId);
        editAcct.signature = TextUtils.nullIfEmpty(signatureView.getText().toString());
        if (!origAcct.equals(editAcct)) {
            doUpdateProfile();
        } else {
            finish();
        }
    }

    private void doUpdateProfile() {
        final MaterialDialog uploadDialog = new MaterialDialog.
                Builder(this).
                content(R.string.updating_wait).
                progress(true, 5000).
                build();
        uploadDialog.show();

        RequestInterceptor restInterceptor = new RequestInterceptor() {
            @Override
            public void intercept(RequestFacade request) {
                request.addHeader("Accept", Constants.APPLICATION_JSON);
            }
        };

        Gson gson = new GsonBuilder()
                .create();

        final OkHttpClient okHttpClient = new OkHttpClient();
        okHttpClient.setReadTimeout(60, TimeUnit.SECONDS);
        okHttpClient.setConnectTimeout(60, TimeUnit.SECONDS);
        okHttpClient.setWriteTimeout(120, TimeUnit.SECONDS);

        RestAdapter restAdapter = new RestAdapter.Builder()
                .setLogLevel(RestAdapter.LogLevel.FULL)
                .setEndpoint(Constants.BASE_URI)
                .setConverter(new GsonConverter(gson))
                .setRequestInterceptor(restInterceptor)
                .setClient(new OkClient(okHttpClient))
                .build();

        UpdateService service = restAdapter.create(UpdateService.class);

        TypedFile avatar = null;
        if (origAcct.avatar != null && editAcct.avatar != null
                && !origAcct.avatar.equals(editAcct.avatar)) {
            avatar = new TypedFile("image/jpg", new File(editAcct.avatar));
        }

        UpdateUserParams params = new UpdateUserParams();
        params.accountId = editAcct.userId;
        params.nickName = editAcct.nickname;
        params.signature = editAcct.signature;

        String reqStr = gson.toJson(params);

        TypedString typedString = new TypedString(reqStr); //"{\"accountId\": \"1\",\"trafficType\": \"traffic-type\",\"title\": \"title\",\"location\": {\"longitude\":\"117.280512\",\"latitude\":\"39.154618\",\"locType\":\"GCJ02\",\"time\":\"1446864018768\"},\"createDate\": \"1446864018768\"}");

        service.update(avatar, typedString, new retrofit.Callback<AccountUpdateResponse>() {
            @Override
            public void success(AccountUpdateResponse reply, Response response) {
                if (response.getStatus() == 200 && reply.errorCode.equals("0")) {
                    Account account = reply.account;
                    mAccount = account;
                    AccountManager.getInstance().setAccount(account);

                    updateViews(account);
                    updateStorage(account);

                    Toast.makeText(getApplicationContext(), getResources().getText(R.string.update_ok), Toast.LENGTH_SHORT).show();
                    uploadDialog.dismiss();
                } else {
                    Toast.makeText(getApplicationContext(),
                            getResources().getText(R.string.upload_fail).toString(), Toast.LENGTH_SHORT).show();
                    uploadDialog.dismiss();
                }
                Log.d("response", response.getReason());

                finish();
            }

            @Override
            public void failure(RetrofitError error) {
                uploadDialog.dismiss();
                final Snackbar snackbar = Snackbar.make(mParentView, error.getMessage(), Snackbar.LENGTH_SHORT);
                snackbar.show();
                snackbar.setAction(R.string.cancel, new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        snackbar.dismiss();
                    }
                });
                Log.d("response", error.getMessage());
            }
        });

    }

    private void updateViews(Account account){
        nicknameView.setText(account.mNickName);
        signatureView.setText(account.mSignature);
    }

    private void updateStorage(Account account){
        NoSQLEntity<Account> entity = new NoSQLEntity<Account>(Constants.ACCOUNT_BUCKET, account.mAccountId, account);
        NoSQL.with(GlobalContext.getGlobalContext()).using(Account.class)
                .save(entity);

        Person person = new Person();
        person.setName(account.mNickName);
        person.setMobile(account.mMobile);
        person.setEmail(account.mEmail);
        person.setAddress(account.mAddress);
        PersistUtils.updatePerson(person);
    }

    private void openPopup() {
        final PopupWindow pop = new PopupWindow(this);

        View view = LayoutInflater.from(this).inflate(R.layout.item_popupwindows, null);

        final LinearLayout ll_popup = (LinearLayout) view.findViewById(R.id.ll_popup);

        pop.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
        pop.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
        pop.setBackgroundDrawable(new BitmapDrawable());
        pop.setFocusable(true);
        pop.setOutsideTouchable(true);
        pop.setContentView(view);
        pop.showAtLocation(mParentView, Gravity.BOTTOM, 0, 0);
        pop.update();

        RelativeLayout parent = (RelativeLayout) view.findViewById(R.id.parent);
        Button btCam = (Button) view
                .findViewById(R.id.item_popupwindows_camera);
        Button btPhoto = (Button) view
                .findViewById(R.id.item_popupwindows_Photo);
        Button btCancel = (Button) view
                .findViewById(R.id.item_popupwindows_cancel);
        parent.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                pop.dismiss();
                ll_popup.clearAnimation();
            }
        });
        btCam.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                // take photo
                //getImageFromCameraCapture();
                clickTakePhoto();

                pop.dismiss();
                ll_popup.clearAnimation();
            }
        });
        btPhoto.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                //getImageFromGallery();
                clickPickFromGallery();

                overridePendingTransition(R.anim.activity_translate_in, R.anim.activity_translate_out);
                pop.dismiss();
                ll_popup.clearAnimation();
            }
        });
        btCancel.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                pop.dismiss();
                ll_popup.clearAnimation();
            }
        });
    }

    protected void clickTakePhoto() {

        /**Permission check only required if saving pictures to root of sdcard*/
        int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
        if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
            EasyImage.openCamera(this, 0);
            getIntent().putExtra(Constants.BUNDLE_APP_STATE, AdvertiseManager.AppState.IN_CAMERA_PHOTO.name());
        } else {
            Nammu.askForPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE, new PermissionCallback() {
                @Override
                public void permissionGranted() {
                    EasyImage.openCamera(MyProfileActivity.this, 0);
                    getIntent().putExtra(Constants.BUNDLE_APP_STATE, AdvertiseManager.AppState.IN_CAMERA_PHOTO.name());
                }

                @Override
                public void permissionRefused() {

                }
            });
        }
    }

    protected void clickPickFromGallery() {
        /** Some devices such as Samsungs which have their own gallery app require write permission. Testing is advised! */
        getIntent().putExtra(Constants.BUNDLE_APP_STATE, AdvertiseManager.AppState.IN_CAMERA_PHOTO.name());
        EasyImage.openGallery(this, 0);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        EasyImage.handleActivityResult(requestCode, resultCode, data, this, new DefaultCallback() {
            @Override
            public void onImagePickerError(Exception e, EasyImage.ImageSource source, int type) {
                //Some error handling
            }

            @Override
            public void onImagePicked(File imageFile, EasyImage.ImageSource source, int type) {
                //Handle the image
                Picasso.with(GlobalContext.getGlobalContext())
                        .load(imageFile)
                        .fit().centerInside()
                        .into(avatarView);
                avatarView.setTag(imageFile.getAbsolutePath());
            }

            @Override
            public void onCanceled(EasyImage.ImageSource source, int type) {
                //Cancel handling, you might wanna remove taken photo if it was canceled
                if (source == EasyImage.ImageSource.CAMERA) {
                    File photoFile = EasyImage.lastlyTakenButCanceledPhoto(MyProfileActivity.this);
                    if (photoFile != null) photoFile.delete();
                }
            }
        });
    }

    private Uri getImageUri(Context inContext, Bitmap inImage) {
        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
        String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, "Title", null);
        return Uri.parse(path);
    }

    public String getRealPathFromURI(Uri uri) {
        Cursor cursor = getContentResolver().query(uri, null, null, null, null);
        cursor.moveToFirst();
        int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
        return cursor.getString(idx);
    }

}
